package com.yikome.purchase.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.base.Preconditions;
import com.itmuch.lightsecurity.annotation.PreAuthorize;
import com.yikome.constant.CommonConstant;
import com.yikome.mq.purchase.request.PurchaseReceiveLogisticsRequest;
import com.yikome.mq.purchase.request.PurchaseStorageProductRequest;
import com.yikome.purchase.dto.PendingPurchaseProductExportDTO;
import com.yikome.purchase.dto.PurchaseLogisticsSearchDTO;
import com.yikome.purchase.dto.PurchaseProductSearchDTO;
import com.yikome.purchase.dto.PurchaseSearchDTO;
import com.yikome.purchase.dto.PurchaseSimpleExportDTO;
import com.yikome.purchase.entity.Purchase;
import com.yikome.purchase.entity.PurchaseProduct;
import com.yikome.purchase.request.PendingPurchaseProductRequest;
import com.yikome.purchase.request.PurchaseCreateRequest;
import com.yikome.purchase.request.PurchaseLogisticsRequest;
import com.yikome.purchase.request.PurchaseProductUpdateRequest;
import com.yikome.purchase.request.PurchaseSearchRequest;
import com.yikome.purchase.request.PurchaseUpdateRequest;
import com.yikome.purchase.response.PendingPurchaseProductResponse;
import com.yikome.purchase.schedule.AsyncPurchaseSchedule;
import com.yikome.purchase.service.PurchaseService;
import com.yikome.utils.BeanUtils;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 采购数据控制类:
 * 提供功能:
 * 1.创建采购单 o
 * 2.查询采购单 o
 * 3.取消采购单 o
 * 4.修改采购单基础信息 o
 * 5.采购单商品数量修改 o
 * 6.采购单增加一个商品 o
 * 7.查询采购单明细 o
 * 8.导出采购单明细 o
 */
@Slf4j
@RestController
@RequestMapping("/admin/purchase")
public class PurchaseController {

	@Autowired
	private PurchaseService purchaseService ; 
	
	@GetMapping("/pending")
	@PreAuthorize("hasAnyRoles('admin', 'purchase', 'analysis')")
	public Page<PendingPurchaseProductResponse> pendingPurchase(@PageableDefault(direction = Direction.ASC , sort = {"order_vo.supplier_id"}) Pageable pageable , PendingPurchaseProductRequest pendingPurchaseProductRequest) {
		
		return purchaseService.pendingPurchase(pendingPurchaseProductRequest , pageable);
	}
	
	@GetMapping("/pending/export")
	@PreAuthorize("hasAnyRoles('admin', 'purchase', 'analysis')")
	public String exportPendingPurchase(@PageableDefault(direction = Direction.ASC , sort = {"order_vo.supplier_id"}) Pageable pageable , PendingPurchaseProductRequest pendingPurchaseProductRequest) throws Exception{
		
		Page<PendingPurchaseProductResponse> purchases = purchaseService.pendingPurchase(pendingPurchaseProductRequest , PageRequest.of(0, 100000, Direction.ASC, "order_vo.supplier_id"));
		
		List<PendingPurchaseProductExportDTO> dtos = new ArrayList<>();
		for (PendingPurchaseProductResponse pendingPurchaseProductResponse : purchases) {
			PendingPurchaseProductExportDTO dto = new PendingPurchaseProductExportDTO();
			BeanUtils.copyProperties(pendingPurchaseProductResponse, dto);
			dtos.add(dto);
		}
		
		Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("缺货单商品", "缺货单商品"), PendingPurchaseProductExportDTO.class, dtos);
        
    	String folderPath = CommonConstant.BASE_LOCATION + LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_DATE) + '/' ;
		File fileFolder = new File(folderPath);
		if (!fileFolder.exists())fileFolder.mkdirs();
		
		String fileName = LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_TIME) + "-缺货单数据.xlsx" ;
		
		String filePath = folderPath + fileName ;
		FileOutputStream fos = new FileOutputStream(filePath);
		workbook.write(fos);
        fos.close();
		return filePath ; 
	}
	
	@PostMapping("/create")
	@PreAuthorize("hasAnyRoles('admin', 'purchase', 'analysis')")
	public List<PurchaseCreateRequest> createPurchase(@RequestBody List<PurchaseCreateRequest> purchaseCreateRequests) {
		
		List<PurchaseCreateRequest> errors = new ArrayList<>();
		
		for (PurchaseCreateRequest purchaseCreateRequest : purchaseCreateRequests) {
			try {
				
				purchaseService.createPurchase(purchaseCreateRequest);
				
			}catch (Exception e) {
				purchaseCreateRequest.setErrorMsg(e.getMessage());
				errors.add(purchaseCreateRequest);
			}
		}
		return errors;
	}
	
	@GetMapping("/list")
	@PreAuthorize("hasAnyRoles('admin', 'purchase', 'analysis', 'storehouse', 'finance', 'order')")
	public Page<PurchaseSearchDTO> findPurchase(@PageableDefault(direction = Direction.DESC , sort = {"p_purchase.id"}) Pageable pageable , PurchaseSearchRequest purchaseSearchRequest){
		
		return purchaseService.findPurchase(purchaseSearchRequest , pageable);
		
	}
	
	@GetMapping("/list/export")
	@PreAuthorize("hasAnyRoles('admin', 'purchase', 'analysis', 'storehouse', 'finance', 'order')")
	public String exportPurchase(@PageableDefault(direction = Direction.DESC , sort = {"p_purchase.id"}) Pageable pageable , PurchaseSearchRequest purchaseSearchRequest) throws Exception{
		
		Page<PurchaseSearchDTO> purchases = purchaseService.findPurchase(purchaseSearchRequest , PageRequest.of(0, 100000, Direction.DESC, "p_purchase.id"));
		
		List<PurchaseSearchDTO> exportDatas = new ArrayList<>();
		for (PurchaseSearchDTO purchaseSearchDTO : purchases) {
			
			PurchaseSearchDTO dto = new PurchaseSearchDTO();
			BeanUtils.copyProperties(purchaseSearchDTO, dto);
			
			exportDatas.add(dto);
		}
		
		Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("采购单信息", "采购单信息"), PurchaseSearchDTO.class, exportDatas);
		
		String folderPath = CommonConstant.BASE_LOCATION + LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_DATE) + '/' ;
		File fileFolder = new File(folderPath);
		if (!fileFolder.exists())fileFolder.mkdirs();
		
		String fileName = LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_TIME) + "-采购单.xlsx" ;
		
		String filePath = folderPath + fileName ;
		FileOutputStream fos = new FileOutputStream(filePath);
		workbook.write(fos);
        fos.close();
		return filePath ; 
	}
	
	@GetMapping("/list/simple-export")
	@PreAuthorize("hasAnyRoles('admin', 'purchase', 'analysis', 'storehouse', 'finance', 'order')")
	public String exportSimplePurchase(@PageableDefault(direction = Direction.DESC , sort = {"p_purchase.id"}) Pageable pageable , PurchaseSearchRequest purchaseSearchRequest) throws Exception{
		
		Page<PurchaseSimpleExportDTO> purchases = purchaseService.findSimplePurchase(purchaseSearchRequest , PageRequest.of(0, 100000, Direction.DESC, "p_purchase.id"));
		
		List<PurchaseSimpleExportDTO> exportDatas = new ArrayList<>();
		for (PurchaseSimpleExportDTO purchaseSearchDTO : purchases) {
			
			PurchaseSimpleExportDTO dto = new PurchaseSimpleExportDTO();
			BeanUtils.copyProperties(purchaseSearchDTO, dto);
			
			exportDatas.add(dto);
		}
		
		Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("采购单信息", "采购单信息"), PurchaseSimpleExportDTO.class, exportDatas);
		
		String folderPath = CommonConstant.BASE_LOCATION + LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_DATE) + '/' ;
		File fileFolder = new File(folderPath);
		if (!fileFolder.exists())fileFolder.mkdirs();
		
		String fileName = LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_TIME) + "-采购单.xlsx" ;
		
		String filePath = folderPath + fileName ;
		FileOutputStream fos = new FileOutputStream(filePath);
		workbook.write(fos);
        fos.close();
		return filePath ; 
	}
	
	@PutMapping
	@PreAuthorize("hasAnyRoles('admin', 'purchase', 'analysis')")
	public Purchase updatePurchase(@RequestBody PurchaseUpdateRequest purchaseUpdateRequest) {
		
		Preconditions.checkArgument(StrUtil.isNotBlank(purchaseUpdateRequest.getPurchaseCode()), "未指定要修改的数据项");
		
		return purchaseService.updatePurchase(purchaseUpdateRequest);
		
	}
	
	@GetMapping("/{purchaseCode}/products")
	@PreAuthorize("hasAnyRoles('admin', 'purchase', 'analysis', 'storehouse', 'finance', 'order')")
	public List<PurchaseProductSearchDTO> findPurchaseProduct(@PathVariable("purchaseCode") String purchaseCode){
		
		return purchaseService.findPurchaseProduct(purchaseCode);
	}
	
	@PostMapping("/storage")
	@PreAuthorize("hasAnyRoles('admin', 'purchase', 'storehouse')")
	public List<PurchaseStorageProductRequest> storagePurchaseProduct(@RequestBody List<PurchaseStorageProductRequest> purchaseStorageProductRequests){
		
		List<PurchaseStorageProductRequest> errors = new ArrayList<>();
		
		for (PurchaseStorageProductRequest purchaseStorageProductRequest : purchaseStorageProductRequests) {
			try {
				purchaseService.StorageProduct(purchaseStorageProductRequest);
			}catch (Exception e) {
				purchaseStorageProductRequest.setErrorMsg(e.getMessage());
				errors.add(purchaseStorageProductRequest);
			}
		}
		
		return errors ;
	}
	
	@PostMapping("/remote/storage")
	public Boolean storagePurchaseProduct(@RequestBody PurchaseStorageProductRequest purchaseStorageProductRequest , HttpServletRequest request){
		
		String salt = request.getParameter("salt") ; 
		Preconditions.checkArgument(StrUtil.isNotBlank(salt), "认证标识不存在...");
		
		String md5 = SecureUtil.md5(SecureUtil.md5("storage"));
		Preconditions.checkArgument(StrUtil.equalsIgnoreCase(salt, md5), "访问标识salt不正确...");
		
		purchaseService.StorageProduct(purchaseStorageProductRequest);
		
		return Boolean.TRUE;
	}
	
	@PostMapping("/remote/receiveLogistics")
	public Boolean receivePurchaseLogistics(@RequestBody PurchaseReceiveLogisticsRequest purchaseReceiveLogisticsRequest , HttpServletRequest request){
		
		log.info("receivePurchaseLogistics : ---------------- {}" , purchaseReceiveLogisticsRequest);
		
		return Boolean.TRUE;
	}
	
	@DeleteMapping("/{purchaseCode}")
	@PreAuthorize("hasAnyRoles('admin', 'purchase')")
	public Boolean deletePurchase(@PathVariable("purchaseCode") String purchaseCode) {
		
		purchaseService.deletePurchase(purchaseCode);
		
		return Boolean.TRUE;
	}
	
	@GetMapping("/{purchaseCode}/products/export")
	@PreAuthorize("hasAnyRoles('admin', 'purchase', 'analysis','finance')")
	public String exportPurchaseProduct(@PathVariable("purchaseCode") String purchaseCode , HttpServletResponse response) throws Exception{
		
		List<PurchaseProductSearchDTO> productSearchDTOs = purchaseService.findPurchaseProduct(purchaseCode);
		
		Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(purchaseCode + "-采购单商品", "采购单商品"), PurchaseProductSearchDTO.class, productSearchDTOs);
        
    	String folderPath = CommonConstant.BASE_LOCATION + LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_DATE) + '/' ;
		File fileFolder = new File(folderPath);
		if (!fileFolder.exists())fileFolder.mkdirs();
		
		String fileName = LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_TIME) + "-采购单数据.xlsx" ;
		
		String filePath = folderPath + fileName ;
		FileOutputStream fos = new FileOutputStream(filePath);
		workbook.write(fos);
        fos.close();
		return filePath ; 
	}
	
	/**
	 * 仅允许修改数量-20191030
	 */
	@PutMapping("/{purchaseCode}/products")
	@PreAuthorize("hasAnyRoles('admin', 'purchase')")
	public PurchaseProduct updatePurchaseProduct(@PathVariable("purchaseCode") String purchaseCode ,@RequestBody PurchaseProductUpdateRequest purchaseProductUpdateRequest) {
		
		purchaseProductUpdateRequest.setPurchaseCode(purchaseCode);
		
		return purchaseService.updatePurchaseProduct(purchaseProductUpdateRequest);
		
		
	}
	
	@PostMapping("/{purchaseCode}/products")
	@PreAuthorize("hasAnyRoles('admin', 'purchase')")
	public PurchaseProduct addPurchaseProduct(@PathVariable("purchaseCode") String purchaseCode ,@RequestBody PurchaseProductUpdateRequest purchaseProductUpdateRequest) {
		
		purchaseProductUpdateRequest.setPurchaseCode(purchaseCode);
		
		return purchaseService.addPurchaseProduct(purchaseProductUpdateRequest);
	}
	
	@GetMapping("/{purchaseCode}/logistics")
	@PreAuthorize("hasAnyRoles('admin', 'purchase', 'analysis', 'storehouse', 'finance', 'order')")
	public List<PurchaseLogisticsSearchDTO> findPurchaseLogistics(@PathVariable("purchaseCode") String purchaseCode){
		
		return purchaseService.findPurchaseLogistics(purchaseCode);
	}
	
	@DeleteMapping("/logistics/{logisticsId}")
	@PreAuthorize("hasAnyRoles('admin', 'purchase')")
	public Boolean deleteLogistics(@PathVariable("logisticsId") Long logisticsId) {
		
		purchaseService.deleteLogistics(logisticsId);
		
		return Boolean.TRUE;
	}
	
	@PostMapping("/logistics")
	@PreAuthorize("hasAnyRoles('admin', 'purchase')")
	public List<PurchaseLogisticsRequest> addPurchaseLogistics(@RequestBody List<PurchaseLogisticsRequest> purchaseLogisticsRequests) {
		
		List<PurchaseLogisticsRequest> errors = new ArrayList<>();
		
		for (PurchaseLogisticsRequest purchaseLogisticsRequest : purchaseLogisticsRequests) {
			
			purchaseLogisticsRequest.setCarrierCode(StrUtil.trim(purchaseLogisticsRequest.getCarrierCode()));
			purchaseLogisticsRequest.setLogisticCode(StrUtil.trim(purchaseLogisticsRequest.getLogisticCode()));
			purchaseLogisticsRequest.setLogisticCompany(StrUtil.trim(purchaseLogisticsRequest.getLogisticCompany()));
			purchaseLogisticsRequest.setPurchaseCode(StrUtil.trim(purchaseLogisticsRequest.getPurchaseCode()));
			
			Preconditions.checkArgument(StrUtil.isNotBlank(purchaseLogisticsRequest.getLogisticCode()), "参数信息不完整");
			Preconditions.checkArgument(StrUtil.isNotBlank(purchaseLogisticsRequest.getLogisticCompany()), "参数信息不完整");
			Preconditions.checkArgument(StrUtil.isNotBlank(purchaseLogisticsRequest.getPurchaseCode()), "参数信息不完整");
			
			try {
				purchaseService.addPurchaseLogistics(purchaseLogisticsRequest);
			}catch (Exception e) {
				purchaseLogisticsRequest.setErrorMsg(e.getMessage());
				errors.add(purchaseLogisticsRequest);
				e.printStackTrace();
			}
		}
		return errors ; 
	}
	
	@PutMapping("/logistics")
	@PreAuthorize("hasAnyRoles('admin', 'purchase')")
	public Boolean updatePurchaseLogistics(@RequestBody PurchaseLogisticsRequest purchaseLogisticsRequest) {
		
		purchaseLogisticsRequest.setLogisticCode(StrUtil.trim(purchaseLogisticsRequest.getLogisticCode()));
		purchaseLogisticsRequest.setPurchaseCode(StrUtil.trim(purchaseLogisticsRequest.getPurchaseCode()));
		
		
		Preconditions.checkArgument(StrUtil.isNotBlank(purchaseLogisticsRequest.getLogisticCode()), "参数信息不完整");
		Preconditions.checkArgument(StrUtil.isNotBlank(purchaseLogisticsRequest.getPurchaseCode()), "参数信息不完整");
		Preconditions.checkArgument(!StrUtil.isAllBlank(purchaseLogisticsRequest.getNewLogisticCode(), purchaseLogisticsRequest.getCarrierCode() , purchaseLogisticsRequest.getLogisticCompany()), "参数信息不完整");
		purchaseService.updatePurchaseLogistics(purchaseLogisticsRequest);
		
		return Boolean.TRUE;
	}
}
